package managers.dateManager.endFrozen.beginChange;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import junit.framework.TestCase;

import org.apache.log4j.Logger;
import org.tbjd.client.beans.Task;
import org.tbjd.client.constants.NotificationsConstants;
import org.tbjd.client.constants.TimeConstants;
import org.tbjd.client.exceptions.DateManagerException;
import org.tbjd.client.managers.TaskManager;
import org.tbjd.client.states.StateEndFrozenASAP;
import org.tbjd.client.states.StateEndFrozenSPEC;

import factories.TaskFactory;

/**
 * <p>
 * Test TaskManager's methods
 * </p>
 * <p>
 * <b>Case</b>
 * </p>
 * <p>
 * A task "task" with multiple pred./succ. both in Manual and ASAP ChainingMode
 * </p>
 * <p>
 * <b>Action</b>
 * </p>
 * <p>
 * BeginDate of the task "task" is changed
 * </p>
 * <p>
 * Expected
 * <ul>
 * <li>update Duration and BeginDate of "task"</li>
 * <li>set ChainingMode to Manual for "task"</li>
 * <li>update Successors</li>
 * </ul>
 * </p>
 * 
 * @author Michael Martin
 * @author Antonio Carrozzini
 * @version 1.0
 * 
 */
public class EndFrozen_BeginChange_UpdatePredecessorsAndSuccessors_Medium extends TestCase {

	/*
	 * Task		Begins 		Ends 		Predecessor Successor 	ChainingMode	task +2 days
	 * o p4		1.12.2008 	4.12.2008 	- 			p2 			ASAP 			3.12.2008 - 6.12.2008
	 * o p3		1.1.2009 	2.1.2009 	- 			p2 			ASAP 			3.1.2009 - 4.1.2009
	 * o p1		1.1.2009 	2.1.2009 	-			task		manual 			-
	 * o t1		1.5.2009 	3.5.2009 	- 			- 			ASAP 			-
	 * o p2 	2.1.2009 	3.1.2009 	-			task		ASAP 			4.1.2009 - 5.1.2009
	 * o task 	4.1.2009 	10.1.2009 	-	 		s1, s2	 	ASAP 			6.1.2009 - 10.1.2009
	 * o t2 	1.1.2009 	3.1.2009 	- 			- 			manual 			-
	 * o s1 	11.1.2009 	14.1.2009 	-			- 			ASAP 			11.1.2009 - 14.1.2009
	 * o s2 	15.1.2009 	23.1.2009 	-			s3 			manual 			-
	 * o t3 	5.6.2009 	12.6.2009 	- 			- 			ASAP 			-
	 * o s3 	8.6.2009 	12.6.2009 	- 			- 			ASAP 			8.6.2009 - 12.6.2009
	 */

	private Map<Integer, Object> map = null;
	private Logger log = Logger.getLogger("console");
	private DateFormat df = DateFormat.getInstance();
	private Task task = null;
	private TaskManager dateManager = new TaskManager();
	private static final long ADDED_DAYS = 2;

	protected void setUp() throws Exception {
		df = new SimpleDateFormat("dd.MM.yyyy");

		Task p4 = TaskFactory.getInstance();
		p4.setName("p4");
		p4.setBeginDate(df.parse("1.12.2008"));
		p4.setEndDate(df.parse("4.12.2008"));
		p4.setDuration(72);
		p4.setState(new StateEndFrozenASAP(p4.getState().getDurationModeState()));

		Task p3 = TaskFactory.getInstance();
		p3.setName("p3");
		p3.setBeginDate(df.parse("1.1.2009"));
		p3.setEndDate(df.parse("2.1.2009"));
		p3.setDuration(24);
		p3.setState(new StateEndFrozenASAP(p3.getState().getDurationModeState()));

		Task p1 = TaskFactory.getInstance();
		p1.setName("p1");
		p1.setBeginDate(df.parse("1.1.2009"));
		p1.setEndDate(df.parse("2.1.2009"));
		p1.setDuration(24);
		p1.setState(new StateEndFrozenSPEC(p1.getState().getDurationModeState()));

		Task t1 = TaskFactory.getInstance();
		t1.setName("t1");
		t1.setBeginDate(df.parse("1.5.2009"));
		t1.setEndDate(df.parse("3.5.2009"));
		t1.setDuration(48);
		t1.setState(new StateEndFrozenASAP(t1.getState().getDurationModeState()));

		Task p2 = TaskFactory.getInstance();
		p2.setName("p2");
		p2.setBeginDate(df.parse("2.1.2009"));
		p2.setEndDate(df.parse("3.1.2009"));
		p2.setDuration(24);
		p2.setState(new StateEndFrozenASAP(p2.getState().getDurationModeState()));

		this.task = TaskFactory.getInstance();
		this.task.setName("task");
		this.task.setBeginDate(df.parse("4.1.2009"));
		this.task.setEndDate(df.parse("10.1.2009"));
		this.task.setDuration(144);
		this.task.setState(new StateEndFrozenASAP(task.getState().getDurationModeState()));

		Task t2 = TaskFactory.getInstance();
		t2.setName("t2");
		t2.setBeginDate(df.parse("1.1.2009"));
		t2.setEndDate(df.parse("3.1.2009"));
		t2.setDuration(48);
		t2.setState(new StateEndFrozenSPEC(t2.getState().getDurationModeState()));

		Task s1 = TaskFactory.getInstance();
		s1.setName("s1");
		s1.setBeginDate(df.parse("11.1.2009"));
		s1.setEndDate(df.parse("14.1.2009"));
		s1.setDuration(72);
		s1.setState(new StateEndFrozenASAP(s1.getState().getDurationModeState()));

		Task s2 = TaskFactory.getInstance();
		s2.setName("s2");
		s2.setBeginDate(df.parse("15.1.2009"));
		s2.setEndDate(df.parse("23.1.2009"));
		s2.setDuration(192);
		s2.setState(new StateEndFrozenSPEC(s2.getState().getDurationModeState()));

		Task t3 = TaskFactory.getInstance();
		t3.setName("t3");
		t3.setBeginDate(df.parse("5.6.2009"));
		t3.setEndDate(df.parse("12.6.2009"));
		t3.setDuration(168);
		t3.setState(new StateEndFrozenASAP(t3.getState().getDurationModeState()));

		Task s3 = TaskFactory.getInstance();
		s3.setName("s3");
		s3.setBeginDate(df.parse("8.6.2009"));
		s3.setEndDate(df.parse("12.6.2009"));
		s3.setDuration(168);
		s3.setState(new StateEndFrozenASAP(s3.getState().getDurationModeState()));

		p4.addSuccessor(p2);
		p3.addSuccessor(p2);
		p1.addSuccessor(this.task);
		p2.addSuccessor(this.task);
		this.task.addSuccessor(s1);
		this.task.addSuccessor(s2);
		s2.addSuccessor(s3);

		super.setUp();
	}

	public void testReturnedBeanListNotNull() {
		System.out.println("");
		log.debug(" === testReturnedBeanListNotNull");
		log.debug("original BeginDate = " + df.format(this.task.getBeginDate()));
		log.debug("original EndDate = " + df.format(this.task.getEndDate()));

		Date newBeginDate = null;
		try {
			newBeginDate = df.parse("1.1.2009");

		} catch (ParseException e1) {
			fail(e1.getMessage());

		}
		log.debug("new BeginDate = " + df.format(newBeginDate));

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.TASKMANAGER_ACTION_beginDate, newBeginDate);
		this.map.put(NotificationsConstants.TASKMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.TASKMANAGER_SENDER, null);

		log.debug("call TaskManager...");
		try {
			assertNotNull("Updated bean list isn't null", dateManager.manageDates(map));

		} catch (DateManagerException e) {
			fail(e.getMessage());

		}

	}

	public void testReturnedListSizeIsOk() {
		System.out.println("");
		log.debug(" === testReturnedListSizeIsOk");

		Date newBeginDate = null;
		try {
			newBeginDate = df.parse("6.1.2009");

		} catch (ParseException e1) {
			fail(e1.getMessage());

		}
		log.debug("new BeginDate = " + df.format(newBeginDate));

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.TASKMANAGER_ACTION_beginDate, newBeginDate);
		this.map.put(NotificationsConstants.TASKMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.TASKMANAGER_SENDER, null);

		log.debug("call dateManager...");
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (DateManagerException e) {
			fail(e.getMessage());

		}
		assertEquals("Updated bean list size = 1", 1, updatedBeans.size());

	}

	public void testReturnedDatesAreOk() {
		System.out.println("");
		log.debug(" === testDatesOfReturnedBeans");

		Date newBeginDate = new Date(task.getBeginDate().getTime() + (ADDED_DAYS * TimeConstants.DAY_IN_MILLIS));

		log.debug("new BeginDate = " + df.format(newBeginDate));

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.TASKMANAGER_ACTION_beginDate, newBeginDate);
		this.map.put(NotificationsConstants.TASKMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.TASKMANAGER_SENDER, null);

		log.debug("call dateManager...");
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager.manageDates(this.map);

		} catch (DateManagerException e) {
			fail(e.getMessage());

		}

		for (Task updatedBean : updatedBeans) {
			log.debug(updatedBean.getName() + " \t updated with BeginDate = " + df.format(updatedBean.getBeginDate()) + " , EndDate = "
					+ df.format(updatedBean.getEndDate()));
			try {
				if (updatedBean.getName().equalsIgnoreCase("task")) {
					assertEquals("check task BeginDate", df.parseObject("6.1.2009"), updatedBean.getBeginDate());
					assertEquals("check task EndDate", df.parseObject("10.1.2009"), updatedBean.getEndDate());
				}
				if (updatedBean.getName().equalsIgnoreCase("s1")) {
					assertEquals("check s1 BeginDate", df.parseObject("11.1.2009"), updatedBean.getBeginDate());
					assertEquals("check s1 EndDate", df.parseObject("14.1.2009"), updatedBean.getEndDate());
				}
				if (updatedBean.getName().equalsIgnoreCase("s3")) {
					fail("s3 dates must not change");
				}

			} catch (ParseException e) {
				fail(e.getMessage());

			}
		}
	}

	public void testChainingModeAreOk() {
		System.out.println("");
		log.debug(" === testChainingModeAreOk");

		Date newBeginDate = new Date(this.task.getBeginDate().getTime() + (ADDED_DAYS * TimeConstants.DAY_IN_MILLIS));
		log.debug("new BeginDate = " + df.format(newBeginDate));

		this.map = new HashMap<Integer, Object>();
		this.map.put(NotificationsConstants.TASKMANAGER_ACTION_beginDate, newBeginDate);
		this.map.put(NotificationsConstants.TASKMANAGER_BEAN, this.task);
		this.map.put(NotificationsConstants.TASKMANAGER_SENDER, null);

		log.debug("call dateManager...");
		List<Task> updatedBeans = null;
		try {
			updatedBeans = dateManager .manageDates(this.map);

		} catch (DateManagerException e) {
			fail(e.getMessage());

		}

		for (Task updatedBean : updatedBeans) {
			log.debug(updatedBean.getName() + " \t updated with BeginDate = " + df.format(updatedBean.getBeginDate()) + " , EndDate = "
					+ df.format(updatedBean.getEndDate()) + " " + ((updatedBean.getState().isASAPChainingMode()) ? "ASAP" : "Manually"));

			if (updatedBean.getName().equalsIgnoreCase("p1")) {
				assertFalse("Returned bean is in manual chaining mode", updatedBeans.get(0).getState().isASAPChainingMode());
			}
			if (updatedBean.getName().equalsIgnoreCase("p2")) {
				assertTrue("Returned bean is in ASAP chaining mode", updatedBeans.get(0).getState().isASAPChainingMode());
			}
			if (updatedBean.getName().equalsIgnoreCase("p3")) {
				assertTrue("Returned bean is in ASAP chaining mode", updatedBeans.get(0).getState().isASAPChainingMode());
			}
			if (updatedBean.getName().equalsIgnoreCase("p4")) {
				assertTrue("Returned bean is in ASAP chaining mode", updatedBeans.get(0).getState().isASAPChainingMode());
			}
			if (updatedBean.getName().equalsIgnoreCase("t1")) {
				assertTrue("Returned bean is in ASAP chaining mode", updatedBeans.get(0).getState().isASAPChainingMode());
			}
			if (updatedBean.getName().equalsIgnoreCase("t2")) {
				assertFalse("Returned bean is in manual chaining mode", updatedBeans.get(0).getState().isASAPChainingMode());
			}
			if (updatedBean.getName().equalsIgnoreCase("t3")) {
				assertTrue("Returned bean is in ASAP chaining mode", updatedBeans.get(0).getState().isASAPChainingMode());
			}
			if (updatedBean.getName().equalsIgnoreCase("s1")) {
				assertTrue("Returned bean is in ASAP chaining mode", updatedBeans.get(0).getState().isASAPChainingMode());
			}
			if (updatedBean.getName().equalsIgnoreCase("s2")) {
				assertFalse("Returned bean is in manual chaining mode", updatedBeans.get(0).getState().isASAPChainingMode());
			}
			if (updatedBean.getName().equalsIgnoreCase("s3")) {
				assertTrue("Returned bean is in ASAP chaining mode", updatedBeans.get(0).getState().isASAPChainingMode());
			}
			if (updatedBean.getName().equalsIgnoreCase("task")) {
				assertFalse("Returned bean is in manual chaining mode", updatedBeans.get(0).getState().isASAPChainingMode());
			}
		}
	}
}